package cn.john.hrm.service.impl;

import cn.john.hrm.config.RabbitMQConfig;
import cn.john.hrm.constant.AuthConstant;
import cn.john.hrm.constant.CourseContants;
import cn.john.hrm.constant.GradeLevel;
import cn.john.hrm.doc.CourseDoc;
import cn.john.hrm.domain.Course;
import cn.john.hrm.domain.CourseDetail;
import cn.john.hrm.domain.CourseMarket;
import cn.john.hrm.domain.UserContextInfo;
import cn.john.hrm.dto.CourseDto;
import cn.john.hrm.feign.AddCourseDocClient;
import cn.john.hrm.feign.DeleteCourseDocClient;
import cn.john.hrm.mapper.CourseDetailMapper;
import cn.john.hrm.mapper.CourseMapper;
import cn.john.hrm.mapper.CourseMarketMapper;
import cn.john.hrm.mapper.CourseTypeMapper;
import cn.john.hrm.query.CourseDocQuery;
import cn.john.hrm.service.ICourseService;
import cn.john.hrm.util.AjaxResult;
import cn.john.hrm.util.ValidUtils;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author john
 * @since 2021-06-20
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private CourseMarketMapper courseMarketMapper;
    @Autowired
    private CourseDetailMapper courseDetailMapper;
    @Autowired
    private CourseTypeMapper courseTypeMapper;
    @Autowired
    private AddCourseDocClient addCourseDocClient;
    @Autowired
    private DeleteCourseDocClient deleteCourseDocClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增课程
     * @param courseDto
     * @return
     */
    @Override
    public AjaxResult save(CourseDto courseDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String key = AuthConstant.USER_INFO_KEY + authentication.getPrincipal();
        UserContextInfo userInfo = (UserContextInfo) redisTemplate.opsForValue().get(key);
        // 校验课程等级
        Course course = courseDto.getCourse();
        // 根据id校验后台是否有对应的课程等级
        GradeLevel level = GradeLevel.checkLevelById(course.getGradeId());
        ValidUtils.assertNotNull(level, "课程等级不存在");
        // 存在就将课程名字设置到course中，保存课程基本信息
        course.setGradeName(level.getGradeName());
        course.setTenantId(userInfo.getTenantId());
        course.setTenantName(userInfo.getTenantName());
        course.setUserId(userInfo.getUserId());
        course.setUserName(userInfo.getUserName());
        super.insert(course);
        // 将基本信息id赋值给市场id
        CourseMarket market = courseDto.getCourseMarket();
        market.setId(course.getId());
        // 保存市场信息
        courseMarketMapper.insert(market);
        // 将基本信息id赋值给详情id
        CourseDetail detail = courseDto.getCourseDetail();
        detail.setId(course.getId());
        // 保存详情
        courseDetailMapper.insert(detail);
        return AjaxResult.me();
    }

    /**
     * 下线课程
     * @param id
     * @return
     */
    @Override
    public AjaxResult offLine(Long id) {
        // 校验id
        ValidUtils.assertNotNull(id, "未选择课程");
        // 通过id查询到课程信息
        Course course = super.selectById(id);
        // 判断课程是否已经下线
        if (course.getStatus() == CourseContants.OFF_LINE)
            throw new RuntimeException("课程已下线");
        AjaxResult result = deleteCourseDocClient.delete(id);
        // 判断删除es是否成功，如果失败了则抛错
        if (!result.isSuccess())
            throw new RuntimeException(result.getMessage());
        // 修改状态为下线
        course.setStatus(CourseContants.OFF_LINE);
        // 更新数据库
        super.updateById(course);
        // 返回
        return result;
    }

    /**
     * 批量下线课程
     * @param ids
     * @return
     */
    @Override
    public AjaxResult batchOffLine(List<Long> ids) {
        // 校验id
        ValidUtils.assertNotNull(ids, "未选择课程");
        for (Long id : ids) {
            // 通过id查询到课程信息
            Course course = super.selectById(id);
            if (course.getStatus() == CourseContants.ON_LINE) {
                AjaxResult result = deleteCourseDocClient.delete(id);
                // 判断删除es是否成功，如果失败了则抛错
                if (!result.isSuccess())
                    throw new RuntimeException(result.getMessage());
                // 修改状态为下线
                course.setStatus(CourseContants.OFF_LINE);
                // 更新数据库
                super.updateById(course);
            }
        }
        return AjaxResult.me();
    }

    /**
     * 批量上线课程
     * @param ids
     * @return
     */
    @Override
    public AjaxResult batchOnLine(List<Long> ids) {
        // 校验id
        ValidUtils.assertNotNull(ids, "未选择课程");
        // 循环遍历
        for (Long id : ids) {
            // 通过id查询到课程信息
            Course course = super.selectById(id);
            // 判断课程是否已经上线
            if (course.getStatus() == CourseContants.OFF_LINE) {
                // 获取courseDoc对象
                CourseDoc courseDoc = toCourseDoc(course);
                // 添加到es
                AjaxResult result = addCourseDocClient.add(courseDoc);
                // 判断保存es是否成功，如果失败了则抛错
                if (!result.isSuccess())
                    throw new RuntimeException(result.getMessage());
                // 修改状态为上线
                course.setStatus(CourseContants.ON_LINE);
                // 更新数据库
                super.updateById(course);
            }
        }
        return AjaxResult.me();
    }

    @Override
    public AjaxResult queryCourses(CourseDocQuery query) {
        AjaxResult result = addCourseDocClient.queryCourses(query);
        return result;
    }

    /**
     * 上线课程
     * @param id
     * @return
     */
    @Override
    public AjaxResult onLine(Long id) {
        // 校验id
        ValidUtils.assertNotNull(id, "未选择课程");
        // 通过id查询到课程信息
        Course course = super.selectById(id);
        // 判断课程是否已经上线
        if (course.getStatus() == CourseContants.ON_LINE)
            throw new RuntimeException("课程已上线");
        // 获取courseDoc对象
        CourseDoc courseDoc = toCourseDoc(course);
        // 添加到es
        AjaxResult result = addCourseDocClient.add(courseDoc);
        // 判断保存es是否成功，如果失败了则抛错
        if (!result.isSuccess())
            throw new RuntimeException(result.getMessage());
        // 修改状态为上线
        course.setStatus(CourseContants.ON_LINE);
        // 更新数据库
        super.updateById(course);
        // 课程发布成功，短信、邮件、站内信通知管理员某课程已经上线
        // 如果是同步操作，前台拿不到响应结果
        // 使用异步操作 把要发的消息放入消息队列 搭建第三方通信服务模块 监听队列 消费消息
        // 发短信
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME_TOPIC, "message.sms",course.getName());
        // 发邮件
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME_TOPIC, "message.email",course.getName());
        // 发站内信
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME_TOPIC, "message.system",course.getName());
        // 返回
        return result;
    }

    /**
     * 将课程基本信息、市场信息、课程详情封装成一个DOC
     * @param course
     * @return
     */
    private CourseDoc toCourseDoc(Course course) {
        // 创建CourseDoc对象
        CourseDoc courseDoc = new CourseDoc();
        // 将课程基本信息封装到courseDoc
        BeanUtils.copyProperties(course, courseDoc);
        // 将市场信息封装到courseDoc
        BeanUtils.copyProperties(courseMarketMapper.selectById(course.getId()), courseDoc);
        // 将课程详情封装到courseDoc
        BeanUtils.copyProperties(courseDetailMapper.selectById(course.getId()), courseDoc);
        // 将课程分类名称封装到courseDoc
        courseDoc.setCourseTypeName(courseTypeMapper.selectById(course.getCourseTypeId()).getName());
        // 返回
        return courseDoc;
    }


}
